﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using Java.IO;
using Java.Lang;
using Java.Net;
using Java.Util;
using Org.Apache.Http.Conn.Util;

namespace PCControl
{
    [Service(Exported = true, Name = "PCControl.PCControl.Service")]
    public class MyService : Service
    {
        public const int MYSERVICE_STATE_CONNECTERROR = -1;
        public const int MYSERVICE_STATE_NOCONNECT = 0;
        public const int MYSERVICE_STATE_CONNECTING = 1;
        public const int MYSERVICE_STATE_CONNECTED = 2;

        private int state = MYSERVICE_STATE_NOCONNECT;

        private static readonly int MAX_COUNT = 10;
        private MyBinder myBinder;
        private TcpClient tcpClient = null;
        private UdpReceiveAndtcpSend ura = null;
        private bool finded = false;

        public override void OnCreate()
        {
            base.OnCreate();

            if (myBinder == null)
            {
                myBinder = new MyBinder(this);
            }
            ura = new UdpReceiveAndtcpSend(this);
            ura.Start();
        }

        public override IBinder OnBind(Intent intent)
        {
            return myBinder;
        }

        public class MyBinder : Binder
        {
            public MyService mService;
            public MyBinder(MyService service)
            {
                mService = service;
            }
            public int GetState()
            {
                return mService.state;
            }
            public void Search()
            {
                if (mService.tcpClient != null)
                {
                    mService.tcpClient.CloseSelf();
                }
                new MyService.UpdBroadCast("01握手", mService).Start();
                if (!mService.ura.isRunning)
                {
                    mService.ura.Start();
                }
            }

            public bool SendCommand(string cmd)
            {
                if (IsReady())
                {
                    mService.tcpClient.Send("ml" + cmd);
                    return true;
                }
                return false;
            }

            public void DisConnect()
            {
                if (mService.tcpClient != null)
                {
                    mService.tcpClient.CloseSelf();
                }
                mService.tcpClient = null;
            }

            public bool IsReady()
            {
                if (mService.tcpClient != null)
                {
                    return mService.tcpClient.IsReady();
                }
                return false;
            }

            public IOnMyServiceListener serviceListener = null;
            public void SetOnMyServiceListener(IOnMyServiceListener listener)
            {
                serviceListener = listener;
            }
        }
        public interface IOnMyServiceListener
        {
            void OnConnectSuccess();

            void OnConnectError(string errMsg);

            void OnConnecting(string msg);

            void OnDisConnect();

            void OnCommandSendSuccess(string cmd);
        }
        private class UpdBroadCast : Thread
        {
            MulticastSocket sender = null;
            DatagramPacket dj = null;
            InetAddress group = null;

            byte[] data = new byte[1024];
            MyService mMyService;
            public UpdBroadCast(string dataString, MyService service)
            {
                data = Encoding.UTF8.GetBytes(dataString);
                mMyService = service;
            }
            public override void Run()
            {
                try
                {
                    sender = new MulticastSocket();
                    group = InetAddress.GetByName("255.255.255.255");
                    dj = new DatagramPacket(data, data.Length, group, 6789);

                    if (mMyService.myBinder.serviceListener != null)
                    {
                        mMyService.myBinder.serviceListener.OnConnecting("查找服务端");
                    }
                    mMyService.state = MYSERVICE_STATE_CONNECTING;
                    int i = 0;
                    while (!mMyService.finded && i < MAX_COUNT)
                    {
                        if (mMyService.myBinder.serviceListener != null)
                        {
                            mMyService.myBinder.serviceListener.OnConnecting("第" + (i + 1) + "次尝试");
                        }
                        sender.Send(dj);
                        Sleep(100);
                        i++;
                    }
                    if (!mMyService.finded && mMyService.myBinder.serviceListener != null)
                    {
                        mMyService.state = MYSERVICE_STATE_CONNECTERROR;
                        if (mMyService.myBinder.serviceListener != null)
                        {
                            mMyService.myBinder.serviceListener.OnConnectError("未找到服务端");
                        }
                    }
                    sender.Close();
                }
                catch
                {

                }
            }
        }
        private class UdpReceiveAndtcpSend : Thread
        {
            MulticastSocket ms = null;
            DatagramPacket dp;
            public bool isRunning = true;
            MyService mMyService;
            public UdpReceiveAndtcpSend(MyService service)
            {
                mMyService = service;
            }
            public void Close()
            {
                isRunning = false;
                if (ms != null)
                {
                    ms.Close();
                }
            }

            public override void Run()
            {
                byte[] data = new byte[1024];
                try
                {
                    InetAddress groupAddress = InetAddress.GetByName("224.0.0.1");
                    if (ms == null)
                    {
                        ms = new MulticastSocket(5678);
                    }
                    ms.JoinGroup(groupAddress);
                }
                catch
                {

                }
                while (isRunning)
                {
                    try
                    {
                        dp = new DatagramPacket(data, data.Length);
                        if (ms != null)
                        {
                            ms.Receive(dp);
                        }
                    }
                    catch
                    {

                    }
                    if (dp.Address != null)
                    {
                        string quest_ip = dp.Address.ToString();
                        string host_ip = mMyService.GetLocalHostIp();
                        if (!host_ip.Equals("") && host_ip.Equals(quest_ip.Substring(1)))
                        {
                            continue;
                        }
                    }

                    string codeString = Encoding.UTF8.GetString(dp.GetData(), 0, dp.Length);
                    if (codeString.Equals("02握手"))
                    {
                        if (mMyService.myBinder.serviceListener != null)
                        {
                            mMyService.myBinder.serviceListener.OnConnecting("握手成功");
                        }
                        mMyService.finded = true;
                    }
                    else
                    {
                        continue;
                    }
                    try
                    {
                        string target_ip = dp.Address.ToString();
                        if (target_ip.StartsWith("/"))
                        {
                            target_ip = target_ip.Substring(1);
                        }
                        if (mMyService.tcpClient == null)
                        {
                            mMyService.tcpClient = new TcpClient(target_ip, 5317, mMyService);
                        }
                        mMyService.tcpClient.Start();
                        break;
                    }
                    catch
                    {

                    }
                }
            }
        }
        public class TcpClient : Thread
        {
            private string serverIP = "";
            private int serverPort = 1234;
            private PrintWriter pw;
            private System.IO.Stream is_;
            private DataInputStream dis;
            private bool isRun = true;
            private Socket socket = null;
            byte[] buff = new byte[4096];
            private string rcvMsg;
            private int rcvLen;
            private bool ready = false;
            private MyService mMyService;

            public TcpClient(string ip, int port, MyService myService)
            {
                this.serverIP = ip;
                if (this.serverIP.StartsWith("/"))
                {
                    this.serverIP = this.serverIP.Substring(1);
                }
                this.serverPort = port;
                mMyService = myService;
            }
            public void CloseSelf()
            {
                isRun = false;
            }
            public bool IsReady()
            {
                return ready;
            }
            public void Send(string msg)
            {
                pw.Println(msg);
                pw.Flush();
            }

            public override void Run()
            {
                try
                {
                    socket = new Socket(serverIP, serverPort)
                    {
                        SoTimeout = 500
                    };
                    pw = new PrintWriter(socket.OutputStream, true);
                    is_ = socket.InputStream;
                    dis = new DataInputStream(is_);
                }
                catch (Java.Lang.Exception e)
                {
                    e.PrintStackTrace();
                }
                while (isRun)
                {
                    try
                    {
                        string header, content;
                        rcvLen = dis.Read(buff);
                        rcvMsg = Encoding.UTF8.GetString(buff, 0, rcvLen);
                        if (rcvMsg.Length < 2)
                        {
                            continue;
                        }
                        header = rcvMsg.Substring(0, 2);
                        content = "";
                        if (rcvMsg.Length > 2)
                        {
                            content = rcvMsg.Substring(2, rcvMsg.Length - 2);
                        }
                        switch (header)
                        {
                            case "qt":
                                isRun = false;
                                break;
                            case "mm":
                                if (mMyService.myBinder.serviceListener != null)
                                {
                                    mMyService.myBinder.serviceListener.OnConnecting("验证");
                                }
                                Send("yz验证");
                                break;
                            case "yz":
                                if (mMyService.myBinder.serviceListener != null)
                                {
                                    mMyService.state = MYSERVICE_STATE_CONNECTED;
                                    mMyService.myBinder.serviceListener.OnConnectSuccess();
                                }
                                ready = true;
                                break;
                            case "ml":
                                if (mMyService.myBinder.serviceListener != null)
                                {
                                    mMyService.myBinder.serviceListener.OnCommandSendSuccess(content);
                                }
                                break;
                        }
                    }
                    catch
                    {

                    }
                }

                if (mMyService.myBinder.serviceListener != null)
                {
                    mMyService.state = MYSERVICE_STATE_NOCONNECT;
                    mMyService.myBinder.serviceListener.OnDisConnect();
                }
                try
                {
                    pw.Close();
                    is_.Close();
                    dis.Close();
                    socket.Close();
                }
                catch
                {

                }
            }
        }
        public string GetLocalHostIp()
        {
            string ipaddress = "";
            try
            {
                IEnumeration en = NetworkInterface.NetworkInterfaces;
                // 遍历所用的网络接口
                while (en.HasMoreElements)
                {
                    NetworkInterface nif = (NetworkInterface)en.NextElement();// 得到每一个网络接口绑定的所有ip
                    IEnumeration inet = nif.InetAddresses;
                    // 遍历每一个接口绑定的所有ip
                    while (inet.HasMoreElements)
                    {
                        InetAddress ip = (InetAddress)inet.NextElement();
                        if (!ip.IsLoopbackAddress
                                && InetAddressUtils.IsIPv4Address(ip
                                .HostAddress))
                        {
                            return ip.HostAddress;
                        }
                    }
                }
            }
            catch (SocketException e)
            {
                Log.Error("feige", "获取本地ip地址失败");
                e.PrintStackTrace();
            }
            return ipaddress;
        }

        private string GetLocalIPAddress()
        {
            try
            {
                for (IEnumeration en = NetworkInterface
                        .NetworkInterfaces; en.HasMoreElements;)
                {
                    NetworkInterface intf = (NetworkInterface)en.NextElement();
                    for (IEnumeration enumIpAddr = intf
                            .InetAddresses; enumIpAddr.HasMoreElements;)
                    {
                        InetAddress inetAddress = (InetAddress)enumIpAddr.NextElement();
                        if (!inetAddress.IsLoopbackAddress)
                        {
                            return inetAddress.HostAddress;
                        }
                    }
                }
            }
            catch (SocketException ex)
            {
                //Log.Error(LOG_TAG, ex.ToString());
            }
            return null;
        }
    }
}